package com.immunology.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.immunology.dao.GenericDao;
import com.immunology.exception.DaoException;

@SuppressWarnings("unchecked")
public class GenericDaoImpl<T> extends HibernateDaoSupport implements
		GenericDao<T> {

	public GenericDaoImpl(SessionFactory sessionFactory) {
		setHibernateTemplate(new HibernateTemplate(sessionFactory));
	}

	@Override
	public synchronized T findById(Long id) throws DaoException {
		try {
			return (T) getHibernateTemplate().get(getEntityClass(), id);
		} catch (RuntimeException re) {
			throw new DaoException(re);
		}
	}

	@Override
	public synchronized List<T> getAll() throws DaoException {
		try {
			return (List<T>) getHibernateTemplate().loadAll(getEntityClass());
		} catch (RuntimeException re) {
			throw new DaoException(re);
		}
	}

	@Override
	public synchronized void saveOrUpdate(Collection<T> entities)
			throws DaoException {
		try {
			for (T entity : entities) {
				getHibernateTemplate().saveOrUpdate(entity);
			}
		} catch (RuntimeException re) {
			throw new DaoException(re);
		}
	}

	@Override
	public synchronized void saveOrUpdate(T... entities) throws DaoException {
		saveOrUpdate(Arrays.asList(entities));
	}

	@Override
	public synchronized void update(Collection<T> entities) throws DaoException {
		try {
			for (T entity : entities) {
				getHibernateTemplate().update(entity);
			}
		} catch (RuntimeException re) {
			throw new DaoException(re);
		}
	}

	@Override
	public synchronized void update(T... entities) throws DaoException {
		update(Arrays.asList(entities));
	}

	@Override
	public synchronized void delete(Collection<T> entities) throws DaoException {
		try {
			if (entities != null) {
				for (T entity : entities) {
					getHibernateTemplate().delete(entity);
				}
			}
		} catch (RuntimeException re) {
			throw new DaoException(re);
		}
	}
	
	@Override
	public synchronized void delete(T... entities) throws DaoException {
		delete(Arrays.asList(entities));
	}

	@Override
	public synchronized void deleteAll() throws DaoException {
		try {
			getHibernateTemplate().deleteAll(
					getHibernateTemplate().loadAll(getEntityClass()));
		} catch (RuntimeException re) {
			throw new DaoException(re);
		}
	}
	

	@Override
	public void save(Collection<T> entities) throws DaoException {
		try {
			for (T entity : entities) {
				System.out.println("Saving " + entity.toString());
				getHibernateTemplate().save(entity);
			}
		} catch (RuntimeException re) {
			throw new DaoException(re);
		}
	}

	@Override
	public void save(T... entities) throws DaoException {
		save(Arrays.asList(entities));
	}

	private Class<?> getEntityClass() {
		ParameterizedType superclass = (ParameterizedType) getClass()
				.getGenericSuperclass();
		return (Class<?>) superclass.getActualTypeArguments()[0];
	}

}
